#ifndef CKKS_SRC_BOOTSTRAPPING_COSINE_APPROX_H
#define CKKS_SRC_BOOTSTRAPPING_COSINE_APPROX_H
#include <gmpxx.h>
#include <vector>
#include <cmath>
#include <vector>
#include <iostream>
#include <complex>
#include <tuple>

struct genDeg {
    std::vector<int> a;
    int b;
};
struct genNode {
    std::vector<mpf_class> x;
    std::vector<mpf_class> p;
    std::vector<mpf_class> c;
    int totdeg;
};

class CosineApprox {
public:
    // 默认构造函数
    CosineApprox() = default;
    // 拷贝构造函数
    CosineApprox(const CosineApprox &cipher) = delete;
    CosineApprox &operator = (const CosineApprox &o) = delete;
    // 移动构造函数
    CosineApprox(CosineApprox &&other) = delete;
    CosineApprox &operator = (CosineApprox &&other) = delete;

    // NewFloat creates a new mpf_class element with 1000 bits of precision
    mpf_class NewFloat(double x);
    // BigintCos is an iterative arbitrary precision computation of Cos(x)
    // Iterative process with an error of ~10^{-0.60206*k} after k iterations.
    // Reference: Johansson, B. Tomas, An elementary algorithm to evaluate trigonometric functions to high precision,
    // 2018
    mpf_class BigintCos(const mpf_class &x);
    // BigintSin is an iterative arbitrary precision computation of Sin(x)
    mpf_class BigintSin(const mpf_class &x);

    // maxIndex function
    int maxIndex(const std::vector<double> &array);

    genDeg genDegrees(int degree, int K, double dev);

    genNode genNodes(const std::vector<int> &deg, double dev, int totdeg, int K, int scnum);

    std::vector<std::complex<double>> ApproximateCos(int K, int degree, double dev, int scnum);
};


const double mPI = 3.141592653589793238462643383279502884;

// q0=0x4001b00001的系数
const std::vector<std::complex<double>> evalSineChebyshevCoeff = {
        -0.089175531246104514,  -9.6422667750362632e-17, -0.20071249062061661,    -4.8211333875181316e-17,
        -0.24827380496921539,   -9.6422667750362632e-17, -0.24704539569890321,    -6.1359879477503499e-17,
        -0.077117760314817138,  1.0518836481857741e-16,  0.23137402297309934,     2.4982236644412137e-16,
        0.19582115413821302,    3.1556509445573224e-16,  -0.34142301740918241,    -8.7656970682147852e-17,
        0.20101757226159045,    7.0125576545718279e-17,  -0.070602991297352494,   1.0518836481857741e-16,
        0.017264908285417879,   -5.653874608998536e-16,  -0.0031709629107228312,  -5.3909036969520927e-16,
        0.00045818396453026222, -1.753139413642957e-16,  -5.3770362500831539e-05, 1.2381547108853384e-16,
        5.246890244510463e-06,  3.3200077645863495e-16,  -4.3166320707582737e-07, 6.2866483661102906e-16,
};
#endif // CKKS_COSINE_APPROX_H
